package com.lw;

import java.awt.*;

/**
 * 顶层地图
 * 绘制顶层组件
 * 判断逻辑
 */
public class MapTop {

    int temp_x,temp_y;//格子位置

    /**
     * 重置游戏
     */
    void resetGame(){
        //遍历地图
        for (int i = 1; i <= GameUtil.MAP_W; i++) {
            for (int j = 1; j <= GameUtil.MAP_H; j++) {
                GameUtil.DATA_TOP[i][j] = 0;
            }
        }
    }

    void logic(){
        temp_x = temp_y = 0;

        if(GameUtil.MOUSE_X>GameUtil.OFFSET&&GameUtil.MOUSE_Y>3*GameUtil.OFFSET){
            //根据鼠标点击的坐标，运算得到地图格子的二维数组下标
            temp_x = (GameUtil.MOUSE_X-GameUtil.OFFSET)/GameUtil.SQUARE_LENGTH+1;
            temp_y = (GameUtil.MOUSE_Y-GameUtil.OFFSET*3)/GameUtil.SQUARE_LENGTH+1;

            //判断是否在二维数组下标内，有可能鼠标点击到地雷区以外
            if(temp_x>=1&&temp_x<=GameUtil.MAP_W&&temp_y>=1&&temp_y<=GameUtil.MAP_H){
                if(GameUtil.LEFT){//鼠标左击
                    if(GameUtil.DATA_TOP[temp_x][temp_y]==0){//覆盖区域
                        GameUtil.DATA_TOP[temp_x][temp_y] = -1;//变为无覆盖区域，-1的话paintSelf中不会绘制图片
                    }
                    spaceOpen(temp_x,temp_y);//打开空格区域
                    GameUtil.LEFT = false;
                }else if(GameUtil.RIGHT){
                    if(GameUtil.DATA_TOP[temp_x][temp_y]==0){//覆盖区域
                        GameUtil.DATA_TOP[temp_x][temp_y] = 1;//变为插旗
                        GameUtil.FLAG_NUM++;
                    }
                    else if(GameUtil.DATA_TOP[temp_x][temp_y]==1){//插旗区域
                        GameUtil.DATA_TOP[temp_x][temp_y] = 0;//变为覆盖
                        GameUtil.FLAG_NUM--;
                    }else if(GameUtil.DATA_TOP[temp_x][temp_y]==-1){//无覆盖
                        numOpen(temp_x,temp_y);
                    }
                    GameUtil.RIGHT = false;
                }
            }
        }

        if(!boom()){
            victory();
        }
    }


    /**
     * 扫雷失败后，显示所有雷
     */
    void seeBoom(){
        //遍历雷区
        for (int i = 1; i <= GameUtil.MAP_W; i++) {
            for (int j = 1; j <= GameUtil.MAP_H; j++) {
                //顶层没插旗，底层是地雷
                if(GameUtil.DATA_TOP[i][j]!=1&&GameUtil.DATA_BOTTOM[i][j]==-1){
                    GameUtil.DATA_TOP[i][j] = -1;//无覆盖
                }
                //顶层是旗，底层不是地雷，显示插错旗
                if(GameUtil.DATA_TOP[i][j]==1&&GameUtil.DATA_BOTTOM[i][j]!=-1){
                    GameUtil.DATA_TOP[i][j] = 2;//插错旗
                }
            }
        }
    }

    /**
     * 胜利判定  true胜利
     * @return
     */
    boolean victory(){
        int count = 0;//统计未打开格子数
        //遍历雷区
        for (int i = 1; i <= GameUtil.MAP_W; i++) {
            for (int j = 1; j <= GameUtil.MAP_H; j++) {
                if(GameUtil.DATA_TOP[i][j]!=-1){
                    count++;
                }
            }
        }
        //未打开格子数和放置的雷数量相等，游戏胜利
        if(count==GameUtil.RAY_MAX){
            //胜利后，将未翻开的区域全部变为旗子
            for (int i = 1; i <= GameUtil.MAP_W; i++) {
                for (int j = 1; j <= GameUtil.MAP_H; j++) {
                    if(GameUtil.DATA_TOP[i][j]==0){
                        GameUtil.DATA_TOP[i][j] = 1;
                    }
                }
            }
            GameUtil.state = 1;
            return true;
        }
        return false;
    }

    /**
     * 失败判定 true失败
     * @return
     */
    boolean boom(){
        if(GameUtil.FLAG_NUM==GameUtil.RAY_MAX){//插旗的数量等于放置地雷的数量
            //遍历雷区
            for (int i = 1; i <= GameUtil.MAP_W; i++) {
                for (int j = 1; j <= GameUtil.MAP_H; j++) {
                    /*
                     * 其实就是有5颗雷，用户放了5个旗子，那么直接把其他区域掀开，
                     * 我不认可这种做法，而且此处的行为影响到victory()方法了，
                     * 导致随便设置5颗旗子后，游戏都能赢，出bug了。
                     */
                    if(GameUtil.DATA_TOP[i][j]==0){
                        GameUtil.DATA_TOP[i][j] = -1;
                    }
                }
            }
        }
        //遍历雷区
        for (int i = 1; i <= GameUtil.MAP_W; i++) {
            for (int j = 1; j <= GameUtil.MAP_H; j++) {
                //顶层无覆盖，底层是地雷，相当于点开格子下面是地雷，扫雷失败
                if(GameUtil.DATA_TOP[i][j]==-1&&GameUtil.DATA_BOTTOM[i][j]==-1){
                    GameUtil.state = 2;
                    seeBoom();//显示所有雷
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 数字翻开
     * 这个方法的功能是，如果翻开的区域下面是数字，在数字格子周围插相应数量旗后，
     * 右键点击标记为数字的格子，则自动翻开周围没有插旗的，和空白的格子
     * 这是因为用户已经确定出现数字的格子周围地雷的位置，则省略其一步步点开的步骤
     * @param x
     * @param y
     */
    void numOpen(int x,int y){
        int count = 0;//记录旗子数

        if(GameUtil.DATA_BOTTOM[x][y]>0){
            //九宫格遍历
            for (int i = x-1; i <=x+1; i++) {
                for (int j = y-1; j <= y+1; j++) {
                    if(GameUtil.DATA_TOP[i][j]==1){//附近有插旗
                        count++;
                    }
                }
            }
            /*
            count是统计标记为数字的格子周围总共插了多少个旗子，
            比如格子中数字为2，附近插了3个旗子，则下面if不成立，不会自动翻开。
            如果相等，则自动翻盖覆盖层和空白格子。
             */
            if(count==GameUtil.DATA_BOTTOM[x][y]){
                //九宫格遍历
                for (int i = x-1; i <=x+1; i++) {
                    for (int j = y-1; j <= y+1; j++) {
                        if(GameUtil.DATA_TOP[i][j]!=1){//没插旗
                            GameUtil.DATA_TOP[i][j] = -1;//无覆盖
                        }
                        //此处要防止递归到非雷区，因为DATA_TOP的数组比雷区大一圈，默认是0，会出现数组越界异常
                        if(i>=1&&j>=1&&i<=GameUtil.MAP_W&&j<=GameUtil.MAP_H){
                            spaceOpen(i,j);//空白处打开
                        }
                    }
                }
            }
        }
    }

    /**
     * 打开空格
     */
    void spaceOpen(int x,int y){
        if(GameUtil.DATA_BOTTOM[x][y]==0){
            //九宫格遍历
            for (int i = x-1; i <=x+1; i++) {
                for (int j = y-1; j <= y+1; j++) {
                    if(GameUtil.DATA_TOP[i][j]!=-1){
                        if(GameUtil.DATA_TOP[i][j]==1){//插旗区域
                            /*
                            没明白，为什么判断出插旗区域，FLAG_NUM就要减一，
                            FLAG_NUM不是用来记录用户插了多少旗子么

                            因为GameUtil.DATA_TOP[i][j] = -1; 本来是1变为-1，自然GameUtil.FLAG_NUM--
                             */
                            GameUtil.FLAG_NUM--;
                        }
                        GameUtil.DATA_TOP[i][j] = -1;
                        //此处要防止递归到非雷区，因为DATA_TOP的数组比雷区大一圈，默认是0，会出现数组越界异常
                        if(i>=1&&j>=1&&i<=GameUtil.MAP_W&&j<=GameUtil.MAP_H){
                            spaceOpen(i,j);
                        }
                    }
                }
            }
        }
    }

    /**
     * 绘制方法
     *
     * @param g
     */
    void paintSelf(Graphics g) {
        logic();
//        if(true) return;
        //遍历地图
        for (int i = 1; i <= GameUtil.MAP_W; i++) {
            for (int j = 1; j <= GameUtil.MAP_H; j++) {
                if (GameUtil.DATA_TOP[i][j] == 0) {//覆盖图片
                    g.drawImage(GameUtil.top,
                            GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.SQUARE_LENGTH - 2,
                            GameUtil.SQUARE_LENGTH - 2,
                            null);
                } else if (GameUtil.DATA_TOP[i][j] == 1) {//插旗图片
                    g.drawImage(GameUtil.flag,
                            GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.SQUARE_LENGTH - 2,
                            GameUtil.SQUARE_LENGTH - 2,
                            null);
                }else if (GameUtil.DATA_TOP[i][j] == 2) {//插错旗图片
                    g.drawImage(GameUtil.noflag,
                            GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.SQUARE_LENGTH - 2,
                            GameUtil.SQUARE_LENGTH - 2,
                            null);
                }

            }
        }
    }
}
